package com.tiennt.android.droidcamreader;

import java.io.File;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Point;
import android.hardware.Camera;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.ToggleButton;

import com.googlecode.tesseract.android.TessBaseAPI;
import com.tiennt.android.droidcamreader.camera.CameraManager;

public class CameraActivity extends Activity implements SurfaceHolder.Callback {
	private SurfaceView surfaceView;
	private SurfaceHolder surfaceHolder;
	boolean previewing = false;
	private SharedPreferences prefs;
	private TessBaseAPI mTessBaseAPI;

	private String sourceLanguageCodeOcr;

	public static final String DEFAULT_SOURCE_LANGUAGE_CODE = "eng";
	public static final String DEFAULT_TRAINED_DATA_FOLDER = "traineddata";
	public static final String TAG = "Camera Activity";

	private RelativeLayout relControls;
	private RelativeLayout relTranslate;

	RelativeLayout relOneShotResult;
	ImageView imvSrcImage;
	private ProgressBar progressTranslating;

	TextView txtSrcText;
	TextView txtTranslatedText;
	ToggleButton btnTorch;
	private Button btnCapture;
	private CropView cropView;
	private ProgressBar progressTranslate;
	private EditText txtResult;

	private CameraManager mCamManager;
	private CameraActivityHandler mHandler;
	boolean hasSurface = false;
	boolean isEngineReady = false;

	public TessBaseAPI getBaseApi() {
		return mTessBaseAPI;
	}

	public void setBaseApi(TessBaseAPI baseApi) {
		this.mTessBaseAPI = baseApi;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		requestWindowFeature(Window.FEATURE_NO_TITLE);

		setContentView(R.layout.camera_activity);
		mCamManager = new CameraManager(this);
		mHandler = new CameraActivityHandler(this);
		initViews();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();

		String previousSourceLanguageCodeOcr = sourceLanguageCodeOcr;

		retrievePreferences();

		surfaceView = (SurfaceView) findViewById(R.id.camSurfaceView);
		surfaceHolder = surfaceView.getHolder();
		if (!hasSurface) {
			surfaceHolder.addCallback(this);
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}

		boolean doNewInit = (mTessBaseAPI == null)
				|| !sourceLanguageCodeOcr.equals(previousSourceLanguageCodeOcr);
		if (doNewInit) {
			// Initialize the OCR engine
			File storageDirectory = getInstallDataDirectory();
			if (storageDirectory != null) {
				initOcrEngine(storageDirectory, sourceLanguageCodeOcr);
			}
		} else {
			// We already have the engine initialized, so just start the camera.
			resumeOCR();

		}
		try {
			mCamManager.openCamera();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			AlertDialog.Builder alert = new AlertDialog.Builder(this);
			alert.setTitle("Camera error");
			alert.setMessage("Cannot open camera.");
			alert.setPositiveButton("OK", null);

			AlertDialog dialog = alert.create();
			dialog.show();

			Button btnOK = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
			btnOK.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					finish();
				}
			});
		}
	}

	public void resumeOCR() {
		showControlsAndCropView();
	}

	public File getInstallDataDirectory() {

		String state = Environment.getExternalStorageState();
		if (Environment.MEDIA_MOUNTED.equals(state)) {
			return getExternalFilesDir(DEFAULT_TRAINED_DATA_FOLDER);
		}
		return null;
	}

	private void initOcrEngine(File storageRoot, String languageCode) {

		ProgressDialog initOcrProgress = new ProgressDialog(this);
		initOcrProgress.setTitle("Please wait");
		initOcrProgress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		initOcrProgress.setMessage("Initializing Tesseract engine...");
		initOcrProgress.show();

		mTessBaseAPI = new TessBaseAPI();
		new OcrInitAsyncTask(this, initOcrProgress, storageRoot.toString(),
				languageCode).execute();
	}

	public boolean isNetworkConnected() {
		ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni == null) {
			// There are no active networks.
			return false;
		}
		return true;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		getMenuInflater().inflate(R.menu.main, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		Intent intent;
		switch (item.getItemId()) {
		case R.id.action_settings: {
			intent = new Intent().setClass(this, PreferencesActivity.class);
			startActivity(intent);
			break;
		}
		case R.id.action_about: {

			break;
		}
		}
		return true;
	}

	private void retrievePreferences() {
		prefs = PreferenceManager.getDefaultSharedPreferences(this);

		sourceLanguageCodeOcr = prefs.getString(
				PreferencesActivity.KEY_SOURCE_LANGUAGE_PREFERENCE,
				CameraActivity.DEFAULT_SOURCE_LANGUAGE_CODE);
	}

	private void initViews() {
		btnCapture = (Button) findViewById(R.id.btnCapture);
		btnTorch = (ToggleButton) findViewById(R.id.btnTorch);
		cropView = (CropView) findViewById(R.id.cropView);
		relControls = (RelativeLayout) findViewById(R.id.relControls);

		relTranslate = (RelativeLayout) findViewById(R.id.relTranslate);
		progressTranslate = (ProgressBar) findViewById(R.id.progressTranslate);
		txtResult = (EditText) findViewById(R.id.txtTranslateResult);

		relOneShotResult = (RelativeLayout) findViewById(R.id.relOneShotResult);
		imvSrcImage = (ImageView) findViewById(R.id.imvSrcImage);
		txtSrcText = (TextView) findViewById(R.id.txtSrcText);
		txtTranslatedText = (TextView) findViewById(R.id.txtTranslatedText);
		progressTranslating = (ProgressBar) findViewById(R.id.progressTranslating);

		btnCapture.setOnClickListener(onButtonCaptureClick);
		btnTorch.setOnCheckedChangeListener(onButtonTorchClick);
	}

	private CompoundButton.OnCheckedChangeListener onButtonTorchClick = new CompoundButton.OnCheckedChangeListener() {

		@Override
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			// TODO Auto-generated method stub
			if (isChecked) {
				mCamManager.turnOnTorch();
			} else {
				mCamManager.turnOffTorch();
			}
		}
	};

	private View.OnClickListener onButtonCaptureClick = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			mCamManager.getCamera().autoFocus(new Camera.AutoFocusCallback() {

				@Override
				public void onAutoFocus(boolean success, Camera camera) {
					// TODO Auto-generated method stub
					mCamManager.getCamera().setOneShotPreviewCallback(
							oneShotPreviewCallback);
				}
			});

		}
	};

	Camera.PreviewCallback oneShotPreviewCallback = new Camera.PreviewCallback() {

		@Override
		public void onPreviewFrame(byte[] data, Camera camera) {
			// TODO Auto-generated method stub

			new OcrAsyncTask(CameraActivity.this, data,
					mCamManager.getPreviewSize().x,
					mCamManager.getPreviewSize().y).execute();
		}
	};

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		if (relOneShotResult.getVisibility() == View.VISIBLE) {
			relControls.setVisibility(View.VISIBLE);
			cropView.setVisibility(View.VISIBLE);
			relOneShotResult.setVisibility(View.GONE);
			progressTranslating.setVisibility(View.VISIBLE);
			txtTranslatedText.setText(R.string.txtResult_hint);
		} else {
			super.onBackPressed();
		}
	}

	public CameraManager getCameraManager() {
		return mCamManager;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
		if (previewing) {
			mCamManager.stopPreview();
			previewing = false;
		}

		try {
			mCamManager.setCameraPreview(holder);
			mCamManager.startPreview();
			previewing = true;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			AlertDialog.Builder alert = new AlertDialog.Builder(this)
					.setTitle("Camera Error")
					.setMessage(
							"Cannot connect to camera. Please restart your device.")
					.setPositiveButton("OK", null);

			AlertDialog dialog = alert.create();
			dialog.show();

			Button btnOK = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
			btnOK.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					finish();
				}
			});
		}

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		hasSurface = true;
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		hasSurface = false;
		mCamManager.stopPreview();
		previewing = false;
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		mCamManager.closeCamera();
		previewing = false;
		hideControlsAndCropView();
		if (!hasSurface) {
			SurfaceView surfaceView = (SurfaceView) findViewById(R.id.camSurfaceView);
			SurfaceHolder surfaceHolder = surfaceView.getHolder();
			surfaceHolder.removeCallback(this);
		}
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		if (mTessBaseAPI != null) {
			mTessBaseAPI.end();
		}
		super.onDestroy();
	}

	public Point getScreenDimension() {
		DisplayMetrics metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);
		return new Point(metrics.widthPixels, metrics.heightPixels);
	}

	public CropView getCropView() {
		return cropView;
	}

	public CameraActivityHandler getHandler() {
		return mHandler;
	}

	public void showControlsAndCropView() {
		relControls.setVisibility(View.VISIBLE);
		cropView.setVisibility(View.VISIBLE);
	}

	public void hideControlsAndCropView() {
		relControls.setVisibility(View.GONE);
		cropView.setVisibility(View.GONE);
	}

	public void showTranslateBar() {
		relTranslate.setVisibility(View.VISIBLE);
	}

	public void hideTranslateBar() {
		relTranslate.setVisibility(View.GONE);
	}

	public void setTranslateResult(String result) {
		progressTranslate.setVisibility(View.GONE);
		txtResult.setText(result);
	}

	public void clearTranslateResult() {
		progressTranslate.setVisibility(View.VISIBLE);
		txtResult.setText("");
	}

	public void showOneShotResult(OcrResult result) {
		relControls.setVisibility(View.GONE);
		cropView.setVisibility(View.GONE);
		relOneShotResult.setVisibility(View.VISIBLE);
		imvSrcImage.setImageBitmap(result.getBitmap());

		txtSrcText.setText(result.getText());
	}

	public void onTranslateResultDelivery(String result) {
		progressTranslating.setVisibility(View.GONE);
		txtTranslatedText.setText(result);

	}
}
